package com.example.lib5.stack;

public class Calculator {
    public static void main(String[] args) {
        //输入计算表达式
        String expression = "30+2*6-22";
        //创建两个栈，数字与符号
        ArrayStack numStack = new ArrayStack(10);
        ArrayStack2 symbolStack = new ArrayStack2(10);
        int index = 0;//字符串后移
        int result=0;
        String keepNum="";

        char c=' ';
        //循环扫描expression
        while (true) {
            //依次得到当前的字符
            c = expression.substring(index, index + 1).charAt(0);
            //当前字符串为字符
            if (symbolStack.isSymbolStack(c)) {
                //判断栈是否为空，空的话就直接加入
                if (symbolStack.isEmpty()) {
                    symbolStack.push(c);
                } else {//不为空的话，就判断优先级
                    //如果加入的优先级比较大，那么就要进行计算
                    int priorityC = symbolStack.priority(c);
                    char peek = (char) symbolStack.peek();
                    int priorityP = symbolStack.priority(peek);
                    if (priorityC <= priorityP) {
                        //获取数字栈的两个值,获取字符的一个值
                        int num1 = numStack.pop();
                        int num2 = numStack.pop();
                        int symbol1 = symbolStack.pop();
                        //计算
                        result = symbolStack.cal(num1, num2, symbol1);
                        //压入栈，结果值压入栈，新添加的值压入栈
                        numStack.push(result);
                        symbolStack.push(c);
                    } else {//优先级大的话就直接加入
                        symbolStack.push(c);
                    }
                }
            }
            //当前字符串为数字,直接加入
            else {
//                numStack.push(c-48);//字符可以跟数字转换的，传过去是一个字符'3',我们要的是3，字符与int差值为48
                //判断是否为最后一个值，如果是的话就直接加入
                keepNum+=c;//字符拼接，
                if (index==expression.length()-1) {
                    numStack.push(Integer.parseInt(keepNum));
                }else {//如果不是的话
                    //判断下一个值是否为字符，如果是的话就加入，不是的话就继续遍历，遍历到后一个是字符为止
                    if (symbolStack.isSymbolStack(expression.substring(index+1,index+2).charAt(0))) {
                        numStack.push(Integer.parseInt(keepNum));
                        keepNum="";
                    }
                }
            }
            //得到的字符后移
            index++;
            //判断字符串是否为最后一个字符串
            if (index >= expression.length()) {
                break;
            }

        }
        while (true) {
            //取出数值栈的两个值
            if (symbolStack.isEmpty()) {
                break;
            }
            //获取数字栈的两个值,获取字符的一个值
            int num1 = numStack.pop();
            int num2 = numStack.pop();
            int symbol1 = symbolStack.pop();
            //计算
            result = symbolStack.cal(num1, num2, symbol1);
            //压入栈，结果值压入栈，新添加的值压入栈
            numStack.push(result);
        }
        System.out.println("字符串"+expression+"的结果为："+result);
    }
}

class ArrayStack2 {

    private int maxSize;
    private int[] stack;
    private int top = -1;

    public ArrayStack2(int maxSize) {
        this.maxSize = maxSize;
        stack = new int[maxSize];
    }

    public boolean isFull() {
        return top == maxSize - 1;
    }

    public boolean isEmpty() {
        return top == -1;
    }

    public void push(int value) {
        //判断是否满了
        if (isFull()) {
            System.out.println("满了无法添加");
            return;
        }
        //设置对应的值
        top++;
        stack[top] = value;
    }

    public int pop() {
        //判断是否为空
        if (isEmpty()) {
            throw new RuntimeException("栈空，没有数据");
        }
        int value = stack[top];
        //取出
        stack[top] = 0;
        top--;
        return value;
    }

    public void list() {
        //判断是否为空
        if (isEmpty()) {
            System.out.println("为空");
            return;
        }
        //倒遍历打印
        System.out.println("遍历结果为-----------------------");
        for (int i = top; i > -1; i--) {
            System.out.println("遍历结果为" + stack[i]);
        }
    }

    /**
     * 判断是否为字符
     * @param symbol
     * @return
     */
    public boolean isSymbolStack(int symbol) {
        return symbol == '+' || symbol == '-' || symbol == '*' || symbol == '/';
    }

    /**
     * 根据值获取优先级
     * @param c 传入的参数
     * @return 返回优先级值
     */
    public int priority(int c) {
        if (c == '*' || c == '/') {
            return 1;
        } else if (c == '+' || c == '-') {
            return 0;
        }else
        return -1;
    }

    /**
     * 查看栈的值
     *
     * @return
     */
    public int peek() {
        return stack[top];
    }

    /**
     * 传入两值与一个符号，根据符号类型来进行计算
     * @param num1
     * @param num2
     * @param symbol
     * @return
     */
    public int cal(int num1, int num2, int symbol) {
        int res = 0;
        switch (symbol) {
            case '+':
                res = num2 + num1;
                break;
            case '-':
                res = num2 - num1;
                break;
            case '*':
                res = num2 * num1;
                break;
            case '/':
                res = num2 / num1;
                break;
            default:
                break;
        }
        return res;
    }
}
